package bdd;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import modele.Balade;
import modele.Docs;
import modele.Noeud;
import modele.Terme;

/*
 * Normalement ca fonctionne !
 */

/**
 * 
 * @author Florence Delrieu & Coralie Micouin
 *
 */
public class RemplirBDD {

	Connection conn;

	public RemplirBDD(Balade b) {
		try {
			Class.forName("com.mysql.jdbc.Driver").newInstance();
			String url = "jdbc:mysql://localhost/RepConn";
			conn = DriverManager.getConnection(url, "root", "");
			
			// On supprime les tables
			supprimeTables();
			
			// On cree les tables
			creerTables();
			
			// et on insere les donnees de la balade dans la base
			remplirTables(b);
			
			conn.close();
		} catch (ClassNotFoundException ex) {
			System.err.println(ex.getMessage());
		} catch (IllegalAccessException ex) {
			System.err.println(ex.getMessage());
		} catch (InstantiationException ex) {
			System.err.println(ex.getMessage());
		} catch (SQLException ex) {
			System.err.println(ex.getMessage());
		}
	}

	/**
	 * Methode qui cree les tables dans la base a partir des requetes de creation de Noeud, Terme et Document (+les cles etrangeres)
	 * @throws SQLException
	 */
	public void creerTables() throws SQLException {
		 Statement st = conn.createStatement();
		 
		 // on cree la table Document
		 st.executeUpdate(creerTableDocument());
		 
		 // on cree la table Noeud
		 st.executeUpdate(creerTableNoeud());
		 
		 // on cree la table Terme
		 st.executeUpdate(creerTableTerme());
		 
		 // on cree les contraintes de cles etrangeres
		 st.executeUpdate(creerContrainteFK());
	}

	/**
	 * Methode qui remplit la base en inserant tous les documents, tous les termes et tous les noeuds
	 * @param b
	 * @throws SQLException 
	 */
	public void remplirTables(Balade b) throws SQLException {
		 Statement st = conn.createStatement();
		
		// insere tous les documents de la balade dans la table Document
		for (int i = 0; i < b.getDocuments().size(); i++) {
			 st.executeUpdate(insertDocument(b.getDocuments().get(i)));
		}
		
		// insere tous les termes dans la table Terme
		for (int i = 0; i < b.getTermes().size(); i++) {
			 st.executeUpdate(insertTerme(b.getTermes().get(i)));
		}
		
		// insere tous les noeuds dans la table Noeud
		for (int i = 0; i < b.getNoeuds().size(); i++) {
			 st.executeUpdate(insertNoeud(b.getNoeuds().get(i)));
		}
	}
	
	/**
	 * Methode qui retourne la requete de creation de la table Document dans la base
	 * @return requete de creation de la table Document dans la base
	 */
	public String creerTableDocument() {
		  String codeMySql =	"CREATE TABLE IF NOT EXISTS `Document` (" +
			  						"`idDocument` int(10) unsigned NOT NULL AUTO_INCREMENT," +
		  							"`nomDocument` longtext NOT NULL," +
			  						"PRIMARY KEY (`idDocument`))" +
			  						"ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;"; 

		  return codeMySql ;
	}


	/**
	 * Methode qui retourne la requete de creation de la table Noeud dans la base
	 * @return requete de creation de la table Noeud dans la base
	 */
	public String creerTableNoeud() {
		  String codeMySql =	"CREATE TABLE IF NOT EXISTS `Noeud`" +
		  							"(`idNoeud` int(10) unsigned NOT NULL AUTO_INCREMENT," +
		  							"`xPath` text NOT NULL," +
		  							"`longueur` int(11) NOT NULL," +
		  							"`idDocument` int(10) unsigned NOT NULL," +
		  							"PRIMARY KEY (`idNoeud`)," +
		  							"KEY `idDocument` (`idDocument`))" +
		  							"ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;"; 
		  return codeMySql ;
	}


	/**
	 * Methode qui retourne la requete de creation de la table Terme dans la base
	 * @return requete de creation de la table Terme dans la base
	 */
	public String creerTableTerme() {
		  String codeMySql =	"CREATE TABLE IF NOT EXISTS `Terme` (" +
		  							"`idTerme` int(10) unsigned NOT NULL AUTO_INCREMENT," +
		  							"`terme` varchar(50) NOT NULL," +
		  							"`positions` longtext NOT NULL," +
		  							"`frequences` longtext NOT NULL," +
		  							"`tf` longtext NOT NULL," +
		  							"`idf` longtext NOT NULL," +
		  							"`score` longtext NOT NULL," +
		  							"PRIMARY KEY (`idTerme`)) " +
		  							"ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;"; 
		  
		  return codeMySql ;
	}

	/**
	 * Methode qui retourne la requete de creation des contraintes de cles etrangeres
	 * @return requete de creation des contraintes de cles etrangeres
	 */
	public String creerContrainteFK() {
		  String codeMySql =	"ALTER TABLE `Noeud`" +
		  							"ADD CONSTRAINT `Terme_fk1` FOREIGN KEY (`idDocument`) REFERENCES `Document` (`idDocument`) ON DELETE CASCADE ON UPDATE CASCADE;"; 
		  
		  return codeMySql ;
	}
	
	/**
	 * Methode qui cree la requete pour inserer un noeud dans la table Noeud
	 * @param n : un Noeud
	 * @return la requete pour inserer un noeud dans la table Noeud
	 */
	public String insertNoeud(Noeud n) {
		String codeMySql =	"INSERT INTO Noeud SET " +
								"xPath='" + n.getxPath() + "', " +
								"idDocument='" + n.getIdDocument() + "'," +
								"longueur='" + n.getLongueur() + "';" ; 
		return codeMySql ;
	}
	
	/**
	 * Methode qui cree la requete pour inserer un terme dans la table Terme
	 * @param t : un Terme
	 * @return la requete pour inserer un terme dans la table Terme
	 */
	public String insertTerme(Terme t) {
		String codeMySql =	"INSERT INTO Terme SET " +
								"terme='" + t.getTerme() + "', " +
								"positions='" + t.getPositions() + "'," +
								"frequences='" + t.getFrequences() + "'," +
								"tf='" + t.getTf() + "', " +
								"idf='" + t.getIdf() + "', " +
								"score='" + t.getScore() + "';";
		return codeMySql ;
	}
	
	/**
	 * Methode qui cree la requete pour inserer un document dans la table Document
	 * @return la requete pour inserer un document dans la table Document
	 */
	public String insertDocument(Docs docs) {
		String codeMySql =	"INSERT INTO Document SET " +
								"nomDocument='" + docs.getNomDocument() + "';";
		// Si je fais juste "INSERT INTO Document;" il veut pas
		return codeMySql ;
	}
	
	// methodes pour vider les tables (au cas ou ...)
	
	/**
	 * Methode qui cree la requete pour vider la table Document
	 * Attention => supprimera (surement) aussi des noeuds a cause du cascade.
	 * @return la requete pour vider la table Document
	 */
	public String videDocument() {
		String codeMySql =	"DELETE FROM Document;";
		return codeMySql ;
	}
	
	/**
	 * Methode qui cree la requete pour vider la table Terme
	 * @return la requete pour vider la table Terme
	 */
	public String videTerme() {
		String codeMySql =	"DELETE FROM Terme;";
		return codeMySql ;
	}
	
	/**
	 * Methode qui cree la requete pour vider la table Noeud
	 * @return la requete pour vider la table Noeud
	 */
	public String videNoeud() {
		String codeMySql =	"DELETE FROM Noeud;";
		return codeMySql ;
	}
	
	/**
	 * Methode qui vide toutes les tables
	 * @throws SQLException 
	 */
	public void videTables() throws SQLException {
		 Statement st = conn.createStatement();
		 
		 // on vide la table Noeud
		 st.executeUpdate(videNoeud());
		 
		 // on vide la table Terme
		 st.executeUpdate(videTerme());
		 
		 // on vide la table Document
		 st.executeUpdate(videDocument());
	}
	
	// methodes pour supprimer les tables (au cas ou ...)
	
	/**
	 * Methode qui cree la requete pour supprimer la table Document
	 * Attention a utiliser qu'apres avoir supprimer la table noeud a cause de la fk !
	 * @return la requete pour supprimer la table Document
	 */
	public String supprimeDocument() {
		String codeMySql =	"DROP TABLE IF EXISTS Document;";
		return codeMySql ;
	}
	
	/**
	 * Methode qui cree la requete pour supprimer la table Terme	 
	 * @return la requete pour supprimer la table Terme
	 */
	public String supprimeTerme() {
		String codeMySql =	"DROP TABLE IF EXISTS Terme;";
		return codeMySql ;
	}
	
	/**
	 * Methode qui cree la requete pour supprimer la table Noeud
	 * @return la requete pour supprimer la table Noeud
	 */
	public String supprimeNoeud() {
		String codeMySql =	"DROP TABLE IF EXISTS Noeud;";
		return codeMySql ;
	}

	/**
	 * Methode qui cree la requete pour supprimer la FK Terme_fk1 (Attention la table noeud doit exister !!!)
	 * @return la requete pour supprimer la FK Terme_fk1
	 */
	public String supprimeFK() {
		String codeMySql =	"ALTER TABLE Noeud DROP FOREIGN KEY `Terme_fk1` ;";
		return codeMySql ;
	}

	/**
	 * Methode qui cree la requete pour set la verification des FK
	 * @return la requete pour set la verification des FK
	 */
	public String setFkCheck(int check) {
		String codeMySql ;
		if (check == 0)
			codeMySql =	"SET FOREIGN_KEY_CHECKS = 0;";
		
		else
			codeMySql =	"SET FOREIGN_KEY_CHECKS = 1;";
		
		return codeMySql ;
	}
	
	/**
	 * Methode qui supprime toutes les tables et la FK
	 * @throws SQLException 
	 */
	public void supprimeTables() throws SQLException {
		 Statement st = conn.createStatement();
		 
		 // on supprime la verif des fk
		 st.executeUpdate(setFkCheck(0));		 
			
		DatabaseMetaData dbm = conn.getMetaData();
		// verifie si la table noeud existe
		ResultSet tableNoeud = dbm.getTables (null, null, "Noeud", null);
		if (tableNoeud.next()) {
			 // on supprime la FK (maintenant l'ordre de suppression des tables n'est plus important)
			 st.executeUpdate(supprimeFK());
		}		 
		 // on remet la verif des fk
		 st.executeUpdate(setFkCheck(1));
		 
		 // on supprime la table Noeud
		 st.executeUpdate(supprimeNoeud());
		 
		 // on supprime la table Terme
		 st.executeUpdate(supprimeTerme());
		 
		 // on supprime la table Document
		 st.executeUpdate(supprimeDocument());
	}
}
